using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Xml.Serialization;

namespace GML.BizTalk.ContextAdderPipelineComponent
{
    public class XmlUtils
    {
        /// <summary>
        /// format the input xml with indentation
        /// </summary>
        /// <param name="sUnformattedXml"></param>
        /// <returns></returns>
        public static string FormatXml(string sUnformattedXml)
        {
            string sResult = string.Empty;
            //load unformatted xml into a dom
            XmlDocument xd = new XmlDocument();
            try
            {
                if (sUnformattedXml.Contains("<") && sUnformattedXml.Contains(">"))
                {
                    sResult = sUnformattedXml;
                }
                else
                {
                    sResult = sUnformattedXml.Replace("&lt;", "<").Replace("&gt;", ">");
                }
                xd.LoadXml(sResult);
            }catch(Exception){
                return sResult;
            }

            //will hold formatted xml
            StringBuilder sb = new StringBuilder();

            //pumps the formatted xml into the StringBuilder above
            StringWriter sw = new StringWriter(sb);

            //does the formatting
            XmlTextWriter xtw = null;

            try
            {
                //point the xtw at the StringWriter
                xtw = new XmlTextWriter(sw);

                //we want the output formatted
                xtw.Formatting = Formatting.Indented;

                //get the dom to dump its contents into the xtw 
                xd.WriteTo(xtw);
            }
            finally
            {
                //clean up even if error
                if (xtw != null)
                    xtw.Close();
            }

            //return the formatted xml
            return sb.ToString();
        }

        /// <summary>
        /// remove the namespace of the input xml
        /// </summary>
        /// <param name="oldDoc"></param>
        /// <returns></returns>
        public static System.Xml.XmlDocument RemoveXmlNamesapce(System.Xml.XmlDocument oldDoc)
        {

            string namesp = string.Empty;

            try
            {
                oldDoc.DocumentElement.SetAttribute("xmlns", namesp);
                //oldDoc.DocumentElement.RemoveAllAttributes();
                System.Xml.XmlDocument newDoc = new System.Xml.XmlDocument();

                newDoc.LoadXml(oldDoc.OuterXml);

                return newDoc;


            }
            catch (Exception ex)
            {
                
                throw ex;
            }
        }

        /// <summary>
        /// Deserialize XML document into an object of Type oType
        /// </summary>
        /// <param name="xDoc"></param>
        /// <param name="oType"></param>
        /// <returns></returns>
        public static object Deserialize2Object(XmlDocument xDoc, Type oType)
        {
            try
            {
                return Deserialize2Object(xDoc.DocumentElement.OuterXml, oType);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Deserialize XML string into an object of Type oType
        /// </summary>
        /// <param name="pXmlizedString"></param>
        /// <param name="oType"></param>
        /// <returns></returns>
        public static object Deserialize2Object(string pXmlizedString, Type oType)
        {
            try
            {
                XmlSerializer xs = new XmlSerializer(oType);
                MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(pXmlizedString.Substring(pXmlizedString.IndexOf("<"))));
                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, System.Text.Encoding.UTF8);
                return xs.Deserialize(memoryStream);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Convert UTF8 Byte Array to string
        /// </summary>
        /// <param name="characters"></param>
        /// <returns></returns>
        public static string UTF8ByteArrayToString(byte[] characters)
        {
            try
            {
                System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
                string constructedString = encoding.GetString(characters);
                return (constructedString);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="characters"></param>
        /// <returns></returns>
        public static string UnicodeByteArrayToString(byte[] characters)
        {
            try
            {
                System.Text.UnicodeEncoding encoding = new System.Text.UnicodeEncoding();
                string constructedString = encoding.GetString(characters);
                return (constructedString);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Convert string to UTF8 Byte Array
        /// </summary>
        /// <param name="pXmlString"></param>
        /// <returns></returns>
        public static byte[] StringToUTF8ByteArray(string pXmlString)
        {
            try
            {
                System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
                byte[] byteArray = encoding.GetBytes(pXmlString);
                return byteArray;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pXmlString"></param>
        /// <returns></returns>
        public static byte[] StringToUnicodeByteArray(string pXmlString)
        {
            try
            {
                System.Text.UnicodeEncoding encoding = new System.Text.UnicodeEncoding();
                byte[] byteArray = encoding.GetBytes(pXmlString);
                return byteArray;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pObject"></param>
        /// <param name="oType"></param>
        /// <returns></returns>
        public static string SerializeObject(object pObject, Type oType)
        {
            try
            {
                string XmlizedString = null;
                MemoryStream memoryStream = new MemoryStream();
                //Dim xs As New XmlSerializer(GetType(FilesBatches)) 
                XmlSerializer xs = new XmlSerializer(oType);

                XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, System.Text.Encoding.UTF8);
                
                xs.Serialize(xmlTextWriter, pObject);
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;

                XmlizedString = UTF8ByteArrayToString(memoryStream.ToArray());

                return XmlizedString.Substring(XmlizedString.IndexOf("<"));
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

    }
}
